Skip to content

feat(gateway): [EPIC-INT-01A] 拓宽网关 JSON-RPC 协议簇并桥接真实 Runtime 实例#363

Merged
phantom5099 merged 6 commits into
1024XEngineer:mainfrom
pionxe:feat/epic-int-01a-gateway-runtime-bridge
Apr 19, 2026
Merged

feat(gateway): [EPIC-INT-01A] 拓宽网关 JSON-RPC 协议簇并桥接真实 Runtime 实例#363
phantom5099 merged 6 commits into
1024XEngineer:mainfrom
pionxe:feat/epic-int-01a-gateway-runtime-bridge

Conversation

@pionxe

@pionxe pionxe commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator

🎯 目标 (Motivation & Context)

本 PR 是 [EPIC-INT-01] 全链路贯通 的第一阶段(Backend Only)。 为了彻底解决 TUI 客户端与 Runtime 底层强耦合的问题,我们必须将 Gateway 作为全系统的唯一通信中枢。本阶段的核心目标是在 Gateway 后端“修路建桥”:放开对应的 RPC 协议通道,更新安全白名单,并将真实的 Runtime 实例正式注入网关引擎中。

目前,我们可以通过 Postman 等工具,携带 Token 成功穿透网关的鉴权与参数校验层,直接唤醒底层的大模型。

Closes #360

✨ 主要变更 (Key Changes)

1. 协议通道扩容 (Protocol Expansion)

  • jsonrpc.go 中新增了对 6 个核心运行时方法的解析与归一化支持:gateway.run, gateway.cancel, gateway.compact, gateway.listSessions, gateway.loadSession, gateway.resolvePermission
  • 补齐了上述方法对应的参数解码与校验结构体。

2. 安全与观测白名单放行 (Security & Metrics)

  • 更新 security.go 中的 Strict ACL 策略,将上述 6 个方法加入合法放行列表,彻底消除 method not found 和 403 拦截。
  • metrics.go 中扩展 method 白名单,防止高基数指标收敛器误杀正常的运行时调用。

3. 动态桥接与实例注入 (Runtime Bridge)

  • 新建 gateway_runtime_bridge.go 适配器,处理 Gateway 契约与 Runtime 实例的阻抗匹配。
  • 改造 gateway_commands.go 启动流程:不再传入 nil,而是正式实例化 RuntimePort 并注入到 IPC/Network Server 中。
  • bootstrap.go 中完成 RPC handler 的注册分发,实现端到端的流量路由。

✅ 验收标准 (Acceptance Criteria)

  • Postman 全链路穿透测试通过:使用 Bearer Token 请求 gateway.run,成功通过 Auth 鉴权和参数强校验,流量精准抵达 Runtime。
  • 未知方法依然被网关严格拦截,ACL 防护墙未被破坏。
  • go test ./... 单元测试全量绿灯。
  • go test -race ./... 并发竞态检测通过。

⚠️ 风险提示与回滚 (Risks & Fallback)

  • 纯后端改动:本次提交不涉及 TUI 客户端的任何修改,默认的 neocode 启动链路(本地直连模式)完全不受影响,无兼容性风险。

打通 Gateway 到 Runtime 的后端桥梁,为 TUI 下沉隔离铺平道路:
1. 协议扩容:在 JSON-RPC 路由与参数解析层,全量注册 gateway.run, cancel, compact, list, load, resolve 等 6 个运行时核心方法。
2. 权限放行:在 Strict ACL 与 Metrics 白名单中放行上述方法,消灭方法调用时的 403 拦截与 method_not_found 错误。
3. 动态桥接:新建 runtimeBridge 适配器,并在 neocode gateway 启动命令中正式实例化 RuntimePort 注入网关 Server。
4. 契约闭环:在分发层 (bootstrap.go) 完成 RPC 请求向 Runtime 实体方法的映射与转发。
@codecov

codecov Bot commented Apr 18, 2026

Copy link
Copy Markdown

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

发现 3 个需要处理的问题:

  1. resolve_permission 目前在分发层被强制要求 session_id,与其参数契约不一致,导致无连接绑定场景(尤其 HTTP)请求会被提前拒绝。
  2. gateway.run 未显式传入 run_id 时,ACK 回包中的 run_id 为空,但 runtime 侧会回退到 request_id,会造成客户端事件关联不一致。
  3. runtime 错误详情被原样拼接进网关响应,存在内部信息泄露风险。

另外,协议方法已扩容到 6 个 runtime 方法,但文档中的 JSON-RPC 方法表仍停留在旧集合,建议在同一 PR 同步更新文档避免实现/文档漂移。


// requiresSession 判断指定动作在分发阶段是否必须携带 session_id。
func requiresSession(action FrameAction) bool {
switch action {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requiresSessionFrameActionResolvePermission 也列为必需 session_id。但 gateway.resolvePermission 的参数模型里没有 session_id,且 validateResolvePermissionFrame 也不要求该字段。结果是:在没有连接级 fallback session 的场景(例如典型 HTTP JSON-RPC 请求)会在分发前被 missing required field: session_id 拦截,方法实际上不可用。建议将 resolve_permission 从这里移除,或在协议参数中补齐并明确要求 session_id

Action: FrameActionRun,
RequestID: frame.RequestID,
SessionID: input.SessionID,
RunID: input.RunID,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里返回的 ACK run_id 直接使用 input.RunID。当调用方不传 run_id 时,bridge 会在 convertGatewayRunInput 内回退到 request_id 提交给 runtime,但 ACK 仍返回空 run_id,客户端后续按 ACK 关联事件会出现不一致。建议在进入 runtime 前统一生成/回填最终 run_id,并在 ACK 中返回该最终值。

Comment thread internal/gateway/bootstrap.go Outdated
message = "runtime operation"
}
if err != nil {
message = fmt.Sprintf("%s failed: %s", message, strings.TrimSpace(err.Error()))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runtimeCallFailedFrame 将下游 err.Error() 原样拼接到对外错误消息。对于网络面调用,这可能暴露内部路径、实现细节或底层错误上下文。建议对外返回稳定通用文案(例如 <operation> failed),详细错误仅写入服务端日志。

@pionxe

pionxe commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator Author

@xgopilot

Role

你现在是一位资深的 Go 后端架构师和系统安全专家。你需要对该 PR 进行深度 Code Review。

Task

仔细审查给定的 PR 代码变更。本次改动旨在 Gateway 中放行 gateway.run 等 6 个核心运行时 RPC 方法,并注入实际的 Runtime 实例处理请求。你的核心任务是寻找参数校验漏洞、跨层 Context 断裂、越权访问风险、Goroutine 泄漏以及不安全的文件/错误透传。请忽略基础语法,直击网关和 RPC 层面的架构隐患。

Review Checkpoints (重点审查清单)

  1. 载荷防线与内存安全 (Payload Security & OOM) - 🌟 高危:

    • 定位 jsonrpc.go 中的参数解码逻辑。检查在解析 JSON Payload 时,是否在 io.Reader 层面包裹了类似 http.MaxBytesReader 的大小限制以防内存溢出(OOM)?
    • 检查参数校验结构体。是否存在因缺少必填校验(如 validate:"required")导致 Runtime 层收到零值或空指针而 Panic 的风险?
  2. 鉴权与越权拦截 (Auth & IDOR):

    • 定位 gateway.loadSession, gateway.compact 等涉及资源 ID 的方法处理逻辑。
    • 检查网关不仅校验了 Token,是否在 gateway_runtime_bridge.go 或更下层做到了严格的用户隔离?即:当前 Token 关联的用户,是否被强制校验其对请求中的 SessionID 等资源具有合法访问权,以防横向越权(IDOR)?
  3. 超时机制与级联取消 (Timeouts & Cancellation):

    • 检查 RPC 请求生命周期。当客户端异常断开连接时,Gateway 层是否能触发 Context Cancel 信号,并在 gateway_runtime_bridge.go 中透传给底层的 Runtime 以中断消耗资源的 LLM 请求?
    • 检查 gateway.run 等长时间运行的任务是否被设置了合理的整体超时限制。
  4. 错误包裹与敏感信息泄露 (Error Handling):

    • 检查 gateway_runtime_bridge.go 返回的错误。Runtime 产生的底层错误(可能包含服务器绝对路径、数据库错、敏感依赖配置)是否在经过桥接器时,被妥善脱敏和转换为符合标准的 RPC 错误码,而不是原样透传给前端网络?
  5. 并发陷阱 (Concurrency Safety):

    • 关注 gateway_commands.gobootstrap.go 里的注入逻辑。注入的 Runtime 实例如果要在多 Goroutine 下处理并发到来的 RPC 请求,其入口处是否做好了状态隔离?寻找明显的未加锁共享切片或 map 修改。

Output Format

请以 Markdown 格式输出你的审查报告。要求直奔主题,结构如下:

  1. 🛑 安全/稳定性 Blockers: 指出可能导致 OOM、越权操作、僵尸任务泄漏的具体代码行,并给出修复代码。
  2. ⚠️ 健壮性建议 (Suggestions): 指出 RPC 错误封装不规范、Context 传递不够优雅等细节问题。
  3. ✅ 架构亮点 (Passed): 简要肯定 PR 中防重放、ACL 隔离等做得好的设计。

如果你在某一项中未发现问题,请明确回复“针对 [第 X 项],代码已安全处理”。

@fennoai

fennoai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

🛑 安全/稳定性 Blockers

  1. IDOR / 横向越权风险(gateway.loadSessiongateway.compactgateway.resolvePermission
  • 位置:internal/gateway/network_server.go:465-472internal/gateway/bootstrap.go:185-281internal/cli/gateway_runtime_bridge.go:164-167internal/runtime/runtime.go:221-231
  • 问题:当前仅做了 Bearer Token 有效性校验,但没有“Token -> User/Subject -> Session Ownership”校验链;session_id / request_id 由客户端直接提供并透传到 runtime/store,存在已认证用户访问/操作他人资源的可能。
  • 修复建议(示例):
// 在鉴权后注入主体标识(subject)
ctx = WithRequestSubject(ctx, subjectID)

// 在网关转发前强制做所有权校验
if err := runtimePort.AuthorizeSession(ctx, sessionID); err != nil {
    return errorFrame(frame, NewFrameError(ErrorCodeAccessDenied, "access denied"))
}
  1. 底层错误透传到 RPC 响应,可能泄露敏感信息
  • 位置:internal/gateway/bootstrap.go:302-313
  • 问题:runtimeCallFailedFrame 直接拼接 err.Error() 返回客户端;runtime/store/provider 报错可能包含本地绝对路径、SQL/依赖细节、内部配置信息。
  • 修复建议(示例):
func runtimeCallFailedFrame(frame MessageFrame, err error, operation string) MessageFrame {
    code := ErrorCodeInternalError
    msg := strings.TrimSpace(operation) + " failed"

    if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
        code = ErrorCodeInvalidAction
        msg = strings.TrimSpace(operation) + " timed out or canceled"
    }

    // 仅写服务端日志,不把底层 err 细节回传给客户端
    return errorFrame(frame, NewFrameError(code, msg))
}
  1. 长任务缺少统一超时上限,存在僵尸任务/资源占用风险
  • 位置:internal/gateway/bootstrap.go:150-191, 222-251(直接用入参 ctx 调 runtime)
  • 问题:虽然客户端断连会触发 cancel,但没有网关侧“每个 RPC 操作最大执行时长”硬超时;若客户端不断开且 runtime 卡住,会长期占用资源。
  • 修复建议(示例):
func withRPCDeadline(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
    if d <= 0 { return ctx, func() {} }
    return context.WithTimeout(ctx, d)
}

opCtx, cancel := withRPCDeadline(ctx, gatewayRuntimeTimeout)
defer cancel()
if err := runtimePort.Run(opCtx, input); err != nil { ... }

⚠️ 健壮性建议 (Suggestions)

  1. gateway.run 入参可进一步前置约束,减少下游压力
  • 位置:internal/gateway/protocol/jsonrpc.go:530-567
  • 建议:decodeRunParams 目前主要做 trim;虽然后续 ValidateFrame 会校验 input_text_or_input_parts,但建议在 decode 阶段同步限制 input_parts 数量与文本长度,尽早失败并降低内存/CPU压力。
  1. 建议统一错误码映射策略,避免“全部 internal_error”降低可观测性
  • 位置:internal/gateway/bootstrap.go:302-313
  • 建议:按错误类型映射到稳定 gateway code(如 timeoutnot_foundpermission_denied),对外隐藏细节、对内保留日志。

✅ 架构亮点 (Passed)

  • 针对第 1 项(Payload OOM):代码已安全处理。HTTP 入口已使用 http.MaxBytesReaderinternal/gateway/network_server.go:496),WS 有 MaxPayloadBytesinternal/gateway/network_server.go:590-592),IPC 帧有 maxFrameSize 限制(internal/gateway/server.go:425-488)。
  • 针对第 1 项(必填参数导致 panic):代码已安全处理。compact/loadSession/resolvePermission 在 protocol 层有必填校验;run 在分发校验阶段要求 input_text_or_input_parts
  • 针对第 3 项(断连级联取消):代码已安全处理。HTTP 使用 request.Context(),WS/SSE/IPC 都在连接生命周期内可取消并透传到 runtime。
  • 针对第 5 项(并发陷阱):代码已安全处理。新增注入与中继路径未发现明显未加锁共享 map/slice 写入。

已本地执行:go test ./internal/gateway/... ./internal/cli/...(通过)。未执行 go test -race ./... 全量竞态扫描。

View job run

基于 Code Review 的深度反馈,全面加固网关与 Runtime 的桥接链路,修复以下高危与体验缺陷:

1. 逻辑修正:移除 `resolvePermission` 对 `session_id` 的强制前置校验,修复无会话场景下 HTTP 请求被错误拦截的 Bug。
2. 状态一致性:在分发 `gateway.run` 前统一下游 `run_id` 状态,确保 ACK 回包与底层运行时使用的 ID 严格对应,防止客户端后续事件关联断裂。
3. 安全阻断 (信息泄露):重构错误透传机制,对外彻底屏蔽 `err.Error()` 包含的底层堆栈与敏感细节,仅返回标准化文案,并映射明确的网关错误码(引入稳定的 `timeout`, `invalid_action` 等)。
4. 资源兜底防耗尽:为所有 Runtime 操作(run/compact/load/list 等)增加 30 分钟的硬超时上下文包裹,彻底杜绝下游卡死或异常断连导致的僵尸任务持续占用系统资源。
5. 合规与契约对齐:在会话操作处补充防御 IDOR(越权访问)的安全演进 TODO 声明;同步更新 README 与详细设计文档,彻底对齐扩容后的 JSON-RPC 方法簇与状态码。
@pionxe

pionxe commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator Author

@xgopilot 请你将codecov/patch的覆盖率提升至百分之九十五以上

@fennoai

fennoai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

已完成本次覆盖率提升并推送到当前 PR 分支。

结果

  • 已推送提交:7a6eb7cpionxe/neo-code:feat/epic-int-01a-gateway-runtime-bridge
  • 主要补充测试:
    • internal/cli/gateway_runtime_bridge_test.go(新增,覆盖 Runtime Bridge 关键分支与映射逻辑)
    • internal/gateway/protocol/jsonrpc_test.go(扩展,覆盖新增 JSON-RPC 方法与参数校验分支)

验证

  • go test ./... -covermode=atomic -coverprofile=/tmp/coverage.out 通过
  • go test -race ./... 通过
  • 基于 origin/main...HEAD 与覆盖率文件做本地 patch 统计(仅统计落在 coverage block 的变更行):95.42%688/721

未完成项:无。

View job run

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: pionxe <148670367+pionxe@users.noreply.github.com>
@phantom5099

Copy link
Copy Markdown
Collaborator

@xgopilot 针对本次PR,请给我一份给AIreview用的提示词,针对的是可能存在的风险点、方案是否合理等等。

@fennoai

fennoai Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

可直接用于 AI Review 的提示词

你现在是一名资深 Go 后端架构师 + 网关安全审计专家。请对当前 PR 做深度评审,目标不是语法风格,而是识别高风险缺陷并判断方案是否合理可落地

请基于以下背景开展评审:

  • PR 主题:在 Gateway 扩展 JSON-RPC 方法簇(gateway.run/cancel/compact/listSessions/loadSession/resolvePermission),并桥接真实 Runtime 实例。
  • 关键改动面:protocol/jsonrpc.gogateway/security.gogateway/metrics.gogateway/bootstrap.gogateway_runtime_bridge.gorpc_dispatch.go 及对应测试。
  • 架构约束:保持 TUI -> Runtime -> Provider/ToolManager 边界,不允许跨层直连,不泄漏厂商差异。

请重点审查以下维度:

  1. 参数校验与输入面安全
  • JSON 解码是否有 payload 大小上限与必填字段校验,是否存在空值/零值导致 panic 或异常路径逃逸。
  • gateway.rungateway.resolvePermission 等新增方法是否存在校验不一致(协议层通过、分发层拦截或相反)。
  1. 鉴权与越权(IDOR)
  • 不只验证 Token 有效性,还要验证 session_id/request_id 的资源所有权绑定。
  • 检查 loadSession/compact/resolvePermission 是否可能被已登录用户横向访问他人资源。
  1. 上下文传递与取消链路
  • 客户端断连后,Gateway 的 context cancel 是否稳定传递到 Runtime,避免僵尸任务。
  • 长任务是否有统一超时上限;是否存在只依赖客户端断连才释放资源的问题。
  1. 错误处理与信息泄露
  • 是否把 err.Error() 直接透传到 RPC 响应,导致路径/内部实现/依赖信息外泄。
  • 错误码映射是否稳定、可观测(权限、超时、参数错误、内部错误需可区分)。
  1. 并发安全与状态一致性
  • Runtime 注入后多 goroutine 并发访问是否有共享状态竞争(map/slice/会话状态)。
  • run_idrequest_id 等关键标识在 ACK、事件流、Runtime 入参之间是否一致,是否有回填不一致问题。
  1. 方案合理性(设计层)
  • 本 PR 是否遵守网关职责边界:桥接层只做协议适配,不吞并 runtime 业务逻辑。
  • ACL/metrics 白名单扩展是否最小必要,是否放开过多方法导致攻击面扩大。
  • 是否引入后续阶段难以兼容的技术债(例如协议字段语义不稳定、错误码不可扩展)。
  1. 测试充分性与回归风险
  • 是否覆盖新增方法的正常路径、边界条件、异常分支、并发场景。
  • 是否有“看似通过但未覆盖关键分支”的盲区(特别是 dispatch、bridge、error mapping、cancel/timeout)。

输出要求(必须严格遵守):

  • 仅输出以下 4 个部分,按严重级别排序。
  1. 🛑 Blockers:会导致安全问题、数据越权、资源泄漏或主链路不可用的问题(给出文件+行号、触发条件、影响范围、修复建议)。
  2. ⚠️ Risks:非阻塞但高概率造成线上不稳定或维护成本升高的问题。
  3. ❓ Design Verdict:判断“方案是否合理”,给出结论(合理/部分合理/不合理)及依据。
  4. 🧪 Test Gaps:缺失的关键测试点(给出应补的用例名或场景)。

附加规则:

  • 直接引用代码位置(path:line)。
  • 不写泛泛建议,不写表扬性描述。
  • 如果某检查项确认安全,请明确写:针对[检查项X],未发现问题

说明

以上提示词是按这个 PR 的改动面和风险模型定制,可直接粘贴给任意 AI Review 工具使用。

View job run

@phantom5099

Copy link
Copy Markdown
Collaborator

@xgopilot 你现在是一名资深 Go 后端架构师 + 网关安全审计专家。请对当前 PR 做深度评审,目标不是语法风格,而是识别高风险缺陷并判断方案是否合理可落地

请基于以下背景开展评审:

  • PR 主题:在 Gateway 扩展 JSON-RPC 方法簇(gateway.run/cancel/compact/listSessions/loadSession/resolvePermission),并桥接真实 Runtime 实例。
  • 关键改动面:protocol/jsonrpc.gogateway/security.gogateway/metrics.gogateway/bootstrap.gogateway_runtime_bridge.gorpc_dispatch.go 及对应测试。
  • 架构约束:保持 TUI -> Runtime -> Provider/ToolManager 边界,不允许跨层直连,不泄漏厂商差异。

请重点审查以下维度:

  1. 参数校验与输入面安全
  • JSON 解码是否有 payload 大小上限与必填字段校验,是否存在空值/零值导致 panic 或异常路径逃逸。
  • gateway.rungateway.resolvePermission 等新增方法是否存在校验不一致(协议层通过、分发层拦截或相反)。
  1. 鉴权与越权(IDOR)
  • 不只验证 Token 有效性,还要验证 session_id/request_id 的资源所有权绑定。
  • 检查 loadSession/compact/resolvePermission 是否可能被已登录用户横向访问他人资源。
  1. 上下文传递与取消链路
  • 客户端断连后,Gateway 的 context cancel 是否稳定传递到 Runtime,避免僵尸任务。
  • 长任务是否有统一超时上限;是否存在只依赖客户端断连才释放资源的问题。
  1. 错误处理与信息泄露
  • 是否把 err.Error() 直接透传到 RPC 响应,导致路径/内部实现/依赖信息外泄。
  • 错误码映射是否稳定、可观测(权限、超时、参数错误、内部错误需可区分)。
  1. 并发安全与状态一致性
  • Runtime 注入后多 goroutine 并发访问是否有共享状态竞争(map/slice/会话状态)。
  • run_idrequest_id 等关键标识在 ACK、事件流、Runtime 入参之间是否一致,是否有回填不一致问题。
  1. 方案合理性(设计层)
  • 本 PR 是否遵守网关职责边界:桥接层只做协议适配,不吞并 runtime 业务逻辑。
  • ACL/metrics 白名单扩展是否最小必要,是否放开过多方法导致攻击面扩大。
  • 是否引入后续阶段难以兼容的技术债(例如协议字段语义不稳定、错误码不可扩展)。
  1. 测试充分性与回归风险
  • 是否覆盖新增方法的正常路径、边界条件、异常分支、并发场景。
  • 是否有“看似通过但未覆盖关键分支”的盲区(特别是 dispatch、bridge、error mapping、cancel/timeout)。

输出要求(必须严格遵守):

  • 仅输出以下 4 个部分,按严重级别排序。
  1. 🛑 Blockers:会导致安全问题、数据越权、资源泄漏或主链路不可用的问题(给出文件+行号、触发条件、影响范围、修复建议)。
  2. ⚠️ Risks:非阻塞但高概率造成线上不稳定或维护成本升高的问题。
  3. ❓ Design Verdict:判断“方案是否合理”,给出结论(合理/部分合理/不合理)及依据。
  4. 🧪 Test Gaps:缺失的关键测试点(给出应补的用例名或场景)。

附加规则:

  • 直接引用代码位置(path:line)。
  • 不写泛泛建议,不写表扬性描述。
  • 如果某检查项确认安全,请明确写:针对[检查项X],未发现问题

@fennoai

fennoai Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

🛑 Blockers

  1. 存在明确的资源所有权缺失(IDOR)路径

    • 代码位置:internal/gateway/rpc_dispatch.go:173internal/gateway/rpc_dispatch.go:180internal/gateway/bootstrap.go:198internal/gateway/bootstrap.go:266internal/gateway/bootstrap.go:286internal/gateway/bootstrap.go:263
    • 触发条件:已认证调用方只需持有有效 Token,即可提交任意 session_id / request_id 调用 gateway.compactgateway.loadSessiongateway.resolvePermission
    • 影响范围:在多客户端/多用户场景下可横向读取他人会话、对他人会话执行 compact、或替他人审批工具权限。bootstrap.go:263 的 TODO 也已直接承认该风险尚未落地。
    • 修复建议:在鉴权层建立 token -> subject 映射并注入上下文;在分发到 Runtime 前做 subjectsession_id/request_id 绑定校验,未命中返回 access_denied
  2. gateway.cancel 忽略目标标识,实际为全局取消,存在跨会话拒绝服务风险

    • 代码位置:internal/gateway/bootstrap.go:217internal/gateway/bootstrap.go:223internal/runtime/runtime.go:198internal/runtime/runtime.go:205
    • 触发条件:任意已认证请求调用 gateway.cancel,即触发 CancelActiveRun(),不校验 run_id/session_id
    • 影响范围:可取消“最近活跃运行”而非“目标运行”,并发场景下会取消错误任务,形成横向 DoS。
    • 修复建议:将取消接口改为按 run_id(+session_id) 精确取消;Runtime 侧维护 run_id -> cancel 映射并做 ownership 校验。

⚠️ Risks

  1. gateway.run 响应语义与实现不一致,容易造成长连接占用和错误运维判断

    • 代码位置:internal/gateway/bootstrap.go:174internal/gateway/bootstrap.go:185internal/cli/gateway_runtime_bridge.go:77internal/runtime/input_prepare.go:24internal/runtime/run.go:60
    • 问题:返回文案是 run accepted,但实际是同步执行完整 runtime.Submit -> Run 后才返回 ACK。长任务会长期占用 RPC 请求上下文(上限 30 分钟)。
    • 建议:改为真正异步 accepted-ack(提交即返回,结果走事件流),或将语义改为 completed 并明确 API 契约。
  2. 协议层对未知字段默认忽略,弱化了“强校验”承诺

    • 代码位置:internal/gateway/protocol/jsonrpc.go:544internal/gateway/protocol/jsonrpc.go:605internal/gateway/protocol/jsonrpc.go:666(以及同类 json.Unmarshal 分支)
    • 问题:未启用 DisallowUnknownFields,拼写错误/意外字段会被静默吞掉,增加协议演进时的灰度风险。
    • 建议:关键方法参数改用 json.Decoder + DisallowUnknownFields,并补充兼容策略。

❓ Design Verdict

结论:部分合理。

  • 合理点:桥接层总体保持在 Gateway -> RuntimePort 适配职责内,未见厂商字段外泄到 gateway/runtime 上层。
  • 不合理点:新增方法簇放行后,授权模型仍停留在“Token 有效 + ACL 方法级”而非“资源级授权”,与本 PR 扩展出的会话读写/审批能力不匹配。
  • 针对[检查项1 参数大小上限],未发现问题(IPC/HTTP/WS 均有限制:internal/gateway/server.go:425internal/gateway/server.go:463internal/gateway/network_server.go:496internal/gateway/network_server.go:590)。
  • 针对[检查项4 错误信息泄露],未发现直接透传 err.Error() 到客户端的问题(失败路径统一为稳定错误码/摘要消息,内部细节仅服务端日志)。
  • 针对[检查项5 并发竞态],未发现新增代码中的明显数据竞争;本地执行 go test -race ./internal/gateway/... ./internal/cli/... 通过。

🧪 Test Gaps

  1. TestDispatchRPCRequest_DenyCrossSubjectLoadSession:已认证但 subject 与 session_id 不匹配时必须返回 access_denied
  2. TestHandleCompactFrame_DenyCrossSubjectSessiongateway.compact 的资源所有权负例。
  3. TestHandleResolvePermissionFrame_DenyCrossSubjectRequestIDrequest_id 非本连接/本主体发起时拒绝审批。
  4. TestHandleCancelFrame_CancelByRunIDOnly:验证 gateway.cancel 只能取消目标 run_id,不能取消其他运行。
  5. TestGatewayRun_ClientDisconnectCancelsRuntime(HTTP+WS 各一):客户端断连后 Runtime 任务应被取消,避免僵尸运行。
  6. TestJSONRPCDecode_RejectUnknownFields:对 gateway.run/loadSession/resolvePermission 的未知字段拒绝策略回归测试。

View job run

基于深度安全审计,完成对网关与 Runtime 桥接层的彻底加固与重构,消灭两大 Blocker 级漏洞:

1. IDOR 防护 (Blocker):引入 SubjectID (主体标识) 机制。鉴权层解析 Token 注入 Subject,并在 loadSession、compact、resolvePermission 等操作前强制执行资源所有权 (Ownership) 校验。彻底阻断多客户端场景下的横向越权。
2. Cancel 全局误杀修复 (Blocker):废弃无参的全局取消逻辑。强制 `gateway.cancel` 显式提供 `run_id`,在 Runtime 侧通过精准映射表实现点对点任务终止,杜绝并发场景下的横向 DoS 攻击。
3. 异步任务队列优化 (Risk):重构 `gateway.run` 为标准的 Accepted-ACK 异步模型。网关鉴权后秒回 ACK (含 run_id),将长耗时的推理任务剥离至独立 goroutine,释放 RPC 阻塞队列,并通过 Stream Relay 推送后续事件流。
4. 严格契约校验 (Risk):全量启用 `json.Decoder` 的 `DisallowUnknownFields()` 特性,严厉拒绝任何带有拼写错误或未知字段的 JSON-RPC 载荷,提升协议演进安全性。
@pionxe

pionxe commented Apr 19, 2026

Copy link
Copy Markdown
Collaborator Author

/simplify

@fennoai

fennoai Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

处理结果

已按 /simplify 要求完成本轮处理,并已推送到当前 PR 分支:feat/epic-int-01a-gateway-runtime-bridge

本次先检查了评论日志里的未决 review 点,结论是这 3 条历史问题在当前分支都已修复:

  • resolvePermission 被错误要求 session_id
  • runtimeCallFailedFrame 对外错误透传风险
  • gateway.run ACK 的 run_id 回填不一致

随后调用了 code-simplifier 子代理并吸收低风险简化改动,提交为:eb1dd07

代码简化内容

  • 文件:internal/cli/gateway_runtime_bridge.go
  • 文件:internal/cli/gateway_runtime_bridge_test.go

核心简化:

  • 提取重复的 runtime 可用性检查为 ensureRuntimeAvailable
  • 提取组合校验为 ensureRuntimeAccess(runtime 可用 + Subject 校验)。
  • 统一复用错误常量 bridgeRuntimeUnavailableErrMsg,减少重复字符串。
  • Run/Compact/ResolvePermission/CancelRun/LoadSession 改为统一前置校验路径。
  • 对应测试对齐当前桥接契约并去除旧调用方式,减少重复硬编码。

验证

  • go test ./internal/cli -count=1 通过。
  • go test ./internal/cli ./internal/gateway 通过。
  • go test ./... 未全绿:internal/gateway/protocolTestNormalizeJSONRPCRequestRuntimeMethods 现存失败(gateway.cancelparams 期望与当前实现不一致)。本次未改该模块逻辑,仅记录现状。

提交与推送

  • Commit: eb1dd07
  • Push: fork/feat/epic-int-01a-gateway-runtime-bridge

View job run

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: pionxe <148670367+pionxe@users.noreply.github.com>
@pionxe

pionxe commented Apr 19, 2026

Copy link
Copy Markdown
Collaborator Author

@xgopilot 请你帮我解决CI未通过的问题以及将覆盖率提升至百分之九十五以上

@fennoai

fennoai Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

处理结果

已完成修复并推送到当前 PR 分支:8c22939

本次改动

  • 修复 CI 失败:internal/gateway/protocol/jsonrpc_test.go
    • gateway.cancel 归一化测试补齐必需 params.run_id,并更新断言为 trim 后值。
  • 提升覆盖率:internal/cli/root_test.go
    • 新增 mustReadInheritedWorkdirnil 与缺失 flag 分支测试。
    • 新增 defaultGatewayCommandRunnerbuildGatewayRuntimePort 失败分支测试。
  • 提升覆盖率:internal/gateway/rpc_dispatch_test.go
    • 新增 gateway.run 缺失 session_id 的分发层错误分支测试。
    • 新增 ACL denied 与 frame error 的指标分支测试(覆盖 IncACLDenied 相关路径)。

验证

  • go test ./...
  • go test -race ./...
  • 已推送到分支:pionxe/feat/epic-int-01a-gateway-runtime-bridge

说明:覆盖率阈值以 CI/Codecov 最终计算为准;本次已针对此前低覆盖分支补齐测试点并完成本地回归。

View job run

Generated with [codeagent](https://github.com/qbox/codeagent)

Co-authored-by: pionxe <148670367+pionxe@users.noreply.github.com>
@phantom5099 phantom5099 merged commit af9b1c7 into 1024XEngineer:main Apr 19, 2026
2 checks passed
@fennoai fennoai Bot mentioned this pull request Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EPIC-INT-01A] 阶段 1:网关协议拓宽与 Runtime 桥接 (Backend Only)

3 participants